﻿
namespace CSharpNewFeatures;

public class CsharpDemo9 : CsharpDemoBase
{
    public record Person(string FirstName, string LastName);

    public record Person2(string FirstName, string LastName) { public string[] PhoneNumbers { get; init; } = default!; }
    public record Person3(string FirstName, string LastName, string[] PhoneNumbers);

    public record Person4
    {
        public string FirstName { get; init; } = default!;
        public string LastName { get; init; } = default!;
    };

    public record Teacher(string FirstName, string LastName, int Grade) : Person(FirstName, LastName);

    public record Student(string FirstName, string LastName, int Grade) : Person(FirstName, LastName);



    public override void Run()
    {
        test0();
        test1();
        test2();
        test3();
        test4();
        test5();
    }

    public void test0()
    {
        printTitle("0. Record types");
        Person2 person = new("Nancy", "Davolio");
        Console.WriteLine(person);
    }

    public void test1()
    {
        printTitle("1. Record types");
        var phoneNumbers = new string[2];
        Person3 person1 = new("Nancy", "Davolio", phoneNumbers);
        Person3 person2 = new("Nancy", "Davolio", phoneNumbers);
        Console.WriteLine(person1 == person2); // output: True

        person1.PhoneNumbers[0] = "555-1234";
        Console.WriteLine(person1 == person2); // output: True 
        Console.WriteLine(ReferenceEquals(person1, person2)); // output: False
    }

    public void test2()
    {
        printTitle("2. Record types");
        Person2 person1 = new("Nancy", "Davolio") { PhoneNumbers = new string[1] };
        Console.WriteLine(person1);
        // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }

        Person2 person2 = person1 with { FirstName = "John" };
        Console.WriteLine(person2);
        // output: Person { FirstName = John, LastName = Davolio, PhoneNumbers = System.String[] }
        Console.WriteLine(person1 == person2); // output: False

        person2 = person1 with { PhoneNumbers = new string[1] };
        Console.WriteLine(person2);
        // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }
        Console.WriteLine(person1 == person2); // output: False

        person2 = person1 with { };
        Console.WriteLine(person1 == person2); // output: True
    }

    public void test3()
    {
        printTitle("3. Record types");
        Person teacher = new Teacher("Nancy", "Davolio", 3);
        Person student = new Student("Nancy", "Davolio", 3);
        Student student2 = new Student("Nancy", "Davolio", 3);

        // 注意： record是值比较，不是引用比较, 只要类型相同，所有值一样，则比较就返回True
        Console.WriteLine("student:  " + student);
        Console.WriteLine("student2: " + student2);
        Console.WriteLine("teacher:  " + teacher);
        Console.WriteLine("teacher == student:  " + (teacher == student)); // output: False
        Console.WriteLine("student2 == student: " + (student2 == student)); // output: True
    }

    public void test4()
    {
        printTitle("4. Pattern matching enhancements");
        Console.WriteLine("public static bool IsLetter(this char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';");
        Console.WriteLine('a'.IsLetter());
        Console.WriteLine("public static bool IsLetterOrSeparator(this char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '.' or ',';");
        Console.WriteLine('.'.IsLetterOrSeparator());
    }


    public void test5()
    {
        printTitle("5. Fit and finish features");
        DateTime dt = new(2021, 11, 24);
        Console.WriteLine(dt);
        var f1 = string (DateTime date) => date.ToString("yyyyMMdd_HHmmss");
        Console.WriteLine(f1(new(2021, 11, 24)));


    }
}


public static class ExtensionStudentInfo
{
    public static bool IsLetter(this char c) => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z';


    public static bool IsLetterOrSeparator(this char c) => c is (>= 'a' and <= 'z') or (>= 'A' and <= 'Z') or '.' or ',';

}

